package cn.wolfcode.wolf2w.service.impl;

import cn.wolfcode.wolf2w.domain.Travel;
import cn.wolfcode.wolf2w.domain.TravelComment;
import cn.wolfcode.wolf2w.domain.UserInfo;
import cn.wolfcode.wolf2w.exception.LogicException;
import cn.wolfcode.wolf2w.query.TravelQueryObject;
import cn.wolfcode.wolf2w.repository.TravelRepository;
import cn.wolfcode.wolf2w.service.IDestinationService;
import cn.wolfcode.wolf2w.service.ITravelCommentService;
import cn.wolfcode.wolf2w.service.ITravelService;
import cn.wolfcode.wolf2w.service.IUserInfoService;
import cn.wolfcode.wolf2w.util.DBHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

@Service
public class TravelServiceImpl implements ITravelService {

    @Autowired
    private TravelRepository travelRepository;


    @Autowired
    private IUserInfoService userInfoService;

    @Autowired
    private IDestinationService destinationService;

    @Autowired
    private ITravelCommentService travelCommentService;

    @Autowired
    private MongoTemplate template;

    @Override
    public void save(Travel travel) {
        travel.setId(null);
        travelRepository.save(travel);
    }

    @Override
    public void delete(String id) {
        travelRepository.deleteById(id);
    }

    @Override
    public void update(Travel travel) {
        travelRepository.save(travel);
    }

    @Override
    public Travel get(String id) {
        if(StringUtils.hasLength(id)) {
            Travel travel = travelRepository.findById(id).orElse(null);
            // 前端需要把 目的地和作者拿到, 这里把它们设置进去
            travel.setDest(destinationService.get(travel.getDestId()));
            travel.setAuthor(userInfoService.get(travel.getUserId()));
            return travel;
        }
        return null;
    }

    @Override
    public Page<Travel> query(TravelQueryObject qo) {
        // 创建拼接对象
        Query query = new Query();
        if (qo.getState() != -1){
            query.addCriteria(Criteria.where("state").is(qo.getState()));
        }

        // 判断是否有目的地, 有的就查询目的地下的游记
        if (StringUtils.hasLength(qo.getDestId())) {
            query.addCriteria(Criteria.where("destId").is(qo.getDestId()));
        }

        if (qo.getDay() != null) {
            query.addCriteria(Criteria.where("day").gte(qo.getDay().getMin()).lte(qo.getDay().getMax()));
        }

        if (qo.getPerExpend() != null) {
            query.addCriteria(Criteria.where("perExpend").gte(qo.getPerExpend().getMin()).lte(qo.getPerExpend().getMax()));
        }

        // 使用PageRequest.of,传入当前页 - 1 (记得-1, 因为当前页从0开始), 页面显示条数, 排序规则, 排序的列
        Pageable pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize()
                , qo.getOrderType().getSortType(), qo.getOrderType().getOrderField());
        Page<Travel> travels = DBHelper.query(template, qo, query, pageable, Travel.class);

        for (Travel travel : travels) {
            UserInfo userInfo = userInfoService.get(travel.getUserId());
            travel.setAuthor(userInfo);
        }

        return travels;
    }


    @Override
    public List<Travel> list() {
        return travelRepository.findAll();
    }


    @Override
    public void audit(String id, int state) {
        // 判断travel是否为null
        if(!StringUtils.hasLength(id)) {
            throw new LogicException("参数异常");
        }
        // 拿到游记
        Travel travel = this.get(id);
        // 判断是否是审核操作
        if(state == Travel.STATE_RELEASE) {
            travel.setState(Travel.STATE_RELEASE);
            travel.setReleaseTime(new Date());
        } else {
        // 不是审核操作, 设置状态为未发布状态, 设置发布时间为null
            travel.setState(Travel.STATE_REJECT);
            travel.setReleaseTime(null);
        }
        // 设置最后更改时间
        travel.setLastUpdateTime(new Date());
        this.update(travel);
    }

    @Override
    public void saveOrUpdate(Travel travel, UserInfo userInfo) {


        travel.setDestName(destinationService.get(travel.getDestId()).getName());
        travel.setUserId(userInfo.getId());
        travel.setReleaseTime(new Date());
        travel.setLastUpdateTime(new Date());

        if (!StringUtils.hasLength(travel.getId())){
            travel.setCreateTime(new Date());
            this.save(travel);
        } else {
            Travel tv = this.get(travel.getId());
            travel.setViewnum(tv.getViewnum());
            travel.setReplynum(tv.getReplynum());
            travel.setFavornum(tv.getFavornum());
            travel.setSharenum(tv.getSharenum());
            travel.setThumbsupnum(tv.getThumbsupnum());
            this.update(travel);
        }
    }

    @Override
    public List<Travel> getTravelsByTop3(String destId) {
        Pageable pageable = PageRequest.of(0, 3, Sort.Direction.ASC, "viewNum");
        return travelRepository.findByDestId(destId, pageable);
    }

    @Override
    public List<TravelComment> comments(String travelId) {
        return travelCommentService.findByTravelId(travelId);
    }

    @Override
    public Page<Travel> findByTop5() {
        Pageable pageable = PageRequest.of(0, 5, Sort.Direction.DESC, "thumbsupnum");
        return travelRepository.findAll(pageable);
    }

    @Override
    public void updateState(String id, int state) {
        // 判断travel是否为null
        if(!StringUtils.hasLength(id)) {
            throw new LogicException("参数异常");
        }
        // 拿到游记
        Travel travel = this.get(id);
        // 判断是否已发布
        if(Travel.STATE_RELEASE == travel.getState()) {
            travel.setState(Travel.STATE_WAITING);
            travel.setReleaseTime(new Date());
        } else {
            throw new LogicException("尚未发布");
        }
        // 设置最后更改时间
        travel.setLastUpdateTime(new Date());
        this.update(travel);
    }

    @Override
    public void commentAdd(TravelComment travelComment, UserInfo userInfo) {
        // 回复评论
        // 两种情况: 判断是否有引用id, 有的话, 通过引用id, 把评论塞到引用的评论对象中

        // 把当前用户的字段赋值到当前游记评论的用户字段中
        BeanUtils.copyProperties(userInfo, travelComment);
        // 用户的id 由自己去设置
        travelComment.setUserId(userInfo.getId());
        // 设置创建时间
        travelComment.setCreateTime(new Date());
        // 判断是否有引用游记评论的id
        if(!StringUtils.hasLength(travelComment.getRefComment().getId())) {
            travelComment.setType(TravelComment.TRAVLE_COMMENT_TYPE);
        } else {
            // 有, 通过游记评论的id, 拿到游记评论
            TravelComment comment = travelCommentService.get(travelComment.getRefComment().getId());
            // 将拿到引用的评论设置到当前评论中
            travelComment.setRefComment(comment);
            // 设置评论级别为 评论中的评论
            travelComment.setType(TravelComment.TRAVLE_COMMENT_TYPE_COMMENT);
        }
        // 添加该游记评论到集合中
        travelCommentService.save(travelComment);
    }
}
